闲扯
感觉这题基本就是看的题解,不过还是大概对动态点分治有了些了解吧,决定还是写篇题解记录一下。
题面
Solution
先考虑给出每个点的军队个数怎么办。
我们考虑通过换根 $DP$ 的方式来求解。
具体的,我们设 $sz_u$ 表示 $u$ 的子树中军队个数, $dp_u$ 表示以 $u$ 为根结点时的答案。
考虑换根过程,当前节点为 $u$ ,要换到 $v$ 时,我们有:
可以知道,如果 $dp_v
那么现在要加上修改呢?
这时候就要引进一个黑科技:动态点分治。
动态点分治又称点分树。具体来讲,就是将点分治过程中找出的重心对应连边,最后得到一个树高为 $\log$ 的新树。
我们在这棵树上暴力向上跳,然后 $O(1)$ 或 $O(\log)$ 的进行对每个点的答案的操作,就能保证复杂度为 $O(n\log n)$ 或者 $O(n\log^2 n)$ 。
我们考虑怎么利用这个点分树来维护我们的信息。
这时,我们又要提到一个动态点分治中很重要的思想:维护儿子,维护父亲。
具体的,对这道题来讲,我们维护 $3$ 个数组: $dis1_u,dis2_u,sum_u$ ,分别表示点分树中 $u$ 的子树中的点对 $u$ 的贡献,对 $fa_u$ 的贡献以及子树中的军队数。
考虑怎么计算一个点 $u$ 的答案。
还是类似换根时的想法,我们考虑在点分树上暴力往上跳。
我们设最初的答案 $ans=dis1_u$ 。
然后从 $u$ 开始考虑到根结点的链上的每个点(根结点除外)。
假设当前在 $v$ 点,那么对答案的贡献为 $dis1_{fa_v}-dis2_v+dis_{v,fa_v}\cdot(sum_{fa_v}-sum_v)$ 。
这个画个图大概就能理解了。
然后考虑修改。
类似的,我们也只需要考虑从 $u$ 开始到根结点的链上的每个点(根结点除外),算出对 $dis1_{fa_v},dis2_v$ 的贡献即可。
Code
1 |
|